package Leo.social;

import Leo.security.SystemProperties;
import Leo.social.QQ.OAuth2ConnectionFacotryForQQImpl;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.sql.DataSource;

@Configuration
@EnableSocial //启动spring social,此注解可以写在启动类上
public class SocialConfigAdapterImpl extends SocialConfigurerAdapter {

   @Autowired
   SystemProperties systemProperties;

    @Autowired
    DataSource dataSource;  //数据源

    @Autowired
    ConnectionFactoryLocator connectionFactoryLocator;  //springsocial自带有的

    public SocialConfigAdapterImpl() {
        super();
    }

    /**
     * Default implementation of {@link #addConnectionFactories(ConnectionFactoryConfigurer, Environment)}.
     * Implemented as a no-op, adding no connection factories.
     *
     * @param connectionFactoryConfigurer
     * @param environment
     */
    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
        super.addConnectionFactories(connectionFactoryConfigurer, environment);
//        connectionFactoryConfigurer.addConnectionFactory(createWeixinConnectionFactory()); //微信连接工厂
//        connectionFactoryConfigurer.addConnectionFactory(createTeambitionConnectionFactory()); //teambition
        connectionFactoryConfigurer.addConnectionFactory(createQQConnectionFactory()); // QQ连接工厂
    }

    /**
     * getUserIdSource：该回调方法返回一个 org.springframework.social.UserIdSource 接口的实现对象，用来惟一标识当前用户。
     * getUserIdSource 方法的实现中通过 Spring Security 来获取当前登录用户的信息。
     * @return
     */
    @Override
    public UserIdSource getUserIdSource() {
        System.out.println("触发getUserIdSource");
        return new UserIdSource() {
            @Override
            public String getUserId() {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication == null) {
                    throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
                }
                System.out.println("对应的用户名为" + authentication.getName());
                return authentication.getName();
            }
        };
    }

    /**
     * Default implementation of {@link #getUsersConnectionRepository(ConnectionFactoryLocator)} that creates an in-memory repository.
     * 获取与数据库的连接设定
     *
     * @param connectionFactoryLocator 这个类的作用是查找connectionFactory，当有多个Factory时，就靠他来区分了
     */
    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        //return super.getUsersConnectionRepository(connectionFactoryLocator); 默认是返回一个存储在内存的Repository：InMemoryUsersConnectionRepository
        /**
         * 使用存储在数据库的JdbcUsersConnectionRepository，用来处理connection和db的逻辑，三个参数的意思：
         * dataSource指数据库
         * 查找正确的Factory
         * 数据加解密的方式
         */
//        JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
        JdbcUserConnectionRepositoryImpl repository = new JdbcUserConnectionRepositoryImpl(dataSource, connectionFactoryLocator, Encryptors.noOpText());
//        repository.setTablePrefix("southmax_"); // 设置表前缀，如果公司有表名规格要求，导致表名不能直接是UserConnection，则可以在这里设置前缀,例如表名为southmax_UserConnection
        return repository;
    }

//
//    public ConnectionFactoryForWxImpl createWeixinConnectionFactory(){
//        return new ConnectionFactoryForWxImpl("weixin",WEI_XIN_APP_ID,WEI_XIN_SECRET);
//    }
//
//    public ConnectionFactoryForTbImpl createTeambitionConnectionFactory(){
//        return new ConnectionFactoryForTbImpl("teambition",TEAMBITION_CLIENT_ID,TEAMBITION_CLIENT_SECRET);
//    }

    public OAuth2ConnectionFacotryForQQImpl createQQConnectionFactory() {
        return new OAuth2ConnectionFacotryForQQImpl(systemProperties.QQ_PROVIDER_ID, systemProperties.QQ_APP_ID, systemProperties.QQ_SECRET);
    }

    @Bean
    public SpringSocialConfigurer springSocialConfigurer() {
        SpringSocialConfigurerImpl springSocialConfigurer;
        if(StringUtils.isBlank(systemProperties.SOCIAL_URL)){
            springSocialConfigurer = new SpringSocialConfigurerImpl();
        }else {
            springSocialConfigurer = new SpringSocialConfigurerImpl(systemProperties.SOCIAL_URL);
        }
        if(StringUtils.isNotBlank(systemProperties.SIGN_UP_URL)) {
            springSocialConfigurer.signupUrl(systemProperties.SIGN_UP_URL); //设置注册地址
        }
        if(StringUtils.isNotBlank(systemProperties.SIGN_IN_URL)) {
            springSocialConfigurer.defaultFailureUrl(systemProperties.SIGN_IN_URL); //认证失败的重定向地址
        }
        return springSocialConfigurer;
    }

    /**
     * 用于处理Social注册
     * @return
     */
    @Bean
    public ProviderSignInUtils providerSignInUtils(){
        return new ProviderSignInUtils(connectionFactoryLocator,getUsersConnectionRepository(connectionFactoryLocator));
    }
}
